﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;

namespace Qing.Lang {

    /*
     * 这是整个语言语法解析的部分
     * 首先根据关键字、符号等，讲代码字符串切割为Token序列，
     * 然后再根据Token序列的顺序和语法定义
     * 生成Expr序列
     * 单个Expr对应一个语法树
     */





    /*
     * 定义Token类型
     * 这是从代码到Expr序列的中间形态
     * 存放切割的代码片段、行号、来源
     */
    public class Token {
        public string Str { get; set; } = "";
        public int Line { get; set; } = 0;

        public string Src { get; set; } = "标准输入";

        public Token() {

        }

        public Token(string str, int line, string src) { 
            this.Str = str;
            this.Line = line;
            this.Src = src;
        }
    }

    /*定义解析阶段产生的异常，用来处理语法错误*/
    public class ParseException : Exception {
        public int Line { get; set; } = 0;

        public string Src { get; set; } = "标准输入";

        public ParseException(string msg, int line, string src) : base(msg) {
            this.Line = line;
            this.Src = src;
        }
    }



    /*语法解析类*/
    public class Parser {

        static Parser(){
            /*把所有用到的关键字和符号集合到Makrs中，用于切割代码*/
            Marks.AddRange(KeyMarks);
            Marks.AddRange(AddMarks);
            Marks.AddRange(MulMarks);
            Marks.AddRange(CompareMarks);
            Marks.AddRange(LogicMarks);
            Marks.AddRange(CollMarks);
            Marks.AddRange(SetMarks);
        }

        /*这里定义一般的符号*/
        public static List<string> Marks = new List<string>() { 
            "；；","；",";;",";", "，", ",", "“", "”", "‘", "\"", "、", "~",
        };

        /*定义语言使用的中文关键字*/
        public static List<string> KeyMarks = new List<string>() {
            "元", "空", "真", "假", "如果", "再则", "否则", "当",
            "执行", "直到", "返回", "跳出", "继续", "取反", 
            "异步", "等待", "尝试", "排查", "例行", "抛出", "遍历", "定义",
            "重复", "匹配", "默认"
        };


        /*
         * 下面定义中缀运算符
         * 由于中缀运算符存在优先级差异
         * 分开定义
         */
        public static List<string> AddMarks = new List<string>() {
            "+=", "-=", "+",  "-", 
            "加等", "减等", "加", "减",
            "自加", "自减", 
        };

        public static List<string> MulMarks = new List<string>() {
            "*=", "/=", "%=", "**", "*", "/", "%",
            "乘等", "除等", "模等", "乘方", "乘", "除以", "模",
            "自乘", "自除", "自模"
        };

        public static List<string> CompareMarks = new List<string>() {
            ">=", "<=", "==", "!=", "<>",  ">", "<",
            "大于等于", "小于等于", "等于", "不等于", "大于", "小于",
        };

        public static List<string> LogicMarks = new List<string>() {
            "&&", "||", 
            "且", "或", 
        };

        public static List<string> SetMarks = new List<string>() {
            "=", "：", ":",
            "设为", "为",
        };

        /*定义集合类型的标记符号*/
        public static List<string> CollMarks = new List<string>() {
            "｛", "｝", "【", "】", "（", "）", "《", "》",
            "{", "}", "[", "]", "(", ")",
        };

        /*定义转义字符，用于代码中的字符串进行转义*/
        public static List<(string, char)> transferChar = new List<(string, char)>(){
/*            ("\\“", '“'),*/
            ("\\”", '”'),
            ("\\’", '’'),
            ("\\\"", '\"'),
            ("\\\"", '\"'),
            ("\\n", '\n'),
            ("\\r", '\r'),
            ("\\t", '\t'),
            ("\\f", '\f'),
            ("\\b", '\b'),
            ("\\a", '\a'),
            ("\\\\", '\\'),
        };






        /*
         * 这里定义了行号
         * 每个Parser初始化行号为1
         */
        int line = 1;


        /*
         * 判断字符串从某一位开始，是否以关键标记开头
         * 如果发现是以关键标记开头
         * 就作为切割代码的依据
         */
        public string StartWithMark(string text, int idx) {
            foreach(var item in Marks) {
                if(idx + item.Length <= text.Length) {
                    bool match = true;
                    for(int i=0; i<item.Length; i++) {
                        if (text[idx+i] != item[i]) {
                            match = false;
                            break;
                        }
                    }
                    if (match) {
                        /*以标记开头，返回该标记*/
                        return item;
                    }
                }

            }
            /*返回空字符串，说明不是以标记开头*/
            return "";
        }


        /*切割代码的方法*/
        public List<Token> SliceText(string text, string src) {
            List<Token> ret = new List<Token>(); //定义返回的Token列表
            int startIdx = 0; //当前片段的起点
            int idx = 0; // 当前遍历的序号
            //遍历
            while(idx < text.Length) {
                if (text[idx] == '\n') {
                    /*发现换行，行号加1*/
                    line++;
                }

                if (char.IsWhiteSpace(text[idx])) {
                    /*发现空格，两种情况*/
                    if(startIdx != idx) {
                        /*
                         * 如果当前起点不等于当前序号
                         * 说明前面经过了一个片段
                         * 把这个片段加入到结果列表中
                         * 更新起点
                         */
                        ret.Add(new Token(text.Substring(startIdx, idx - startIdx), line, src));
                        idx++;
                        startIdx = idx;
                        continue;
                    } else {
                        /*
                         * 如果当前起点等于当前序号，说明经过的是连续的空格，更新起点即可
                         */
                        startIdx = idx+1;
                    }
                }

                if (text[idx] == '“' || text[idx] == '‘' || text[idx] == '"') {
                    /*
                     * 当前的字符是字符串类型的起点标记
                     */

                    /*
                     * 如果当前起点不等于当前序号
                     * 说明前面经过了一个片段
                     * 把这个片段加入到结果列表中
                     */
                    if (startIdx != idx) {
                        ret.Add(new Token(text.Substring(startIdx, idx - startIdx), line, src));
                    }

                    /*把字符串作为单个Token加入到结果列表中，并更新起点*/
                    string s = TakeStr(text, idx);
                    ret.Add(new Token(s, line, src));
                    idx += Math.Max(s.Length, 1);
                    startIdx = idx;
                    continue;
                }

                if (text[idx] == '#' || (text[idx] == '@' && (idx >= text.Length-1 || text[idx+1]!='【'|| text[idx+1]!='['))) {
                    if (startIdx != idx) {
                        ret.Add(new Token(text.Substring(startIdx, idx - startIdx), line, src));
                    }
                    string s = TakePath(text, idx);
                    ret.Add(new Token(s, line, src));
                    idx += Math.Max(s.Length, 1);
                    startIdx = idx;
                    continue;
                }


                string mark = StartWithMark(text, idx);
                /*单行注释*/
                if (mark == "；" || mark == ";") {
                    /*
                     * 发现当前是分号，处理前面的片段，然后一直找到换行
                     * 分号是注释标记，不进入语法解析
                     * 直接更新起点
                     */
                    if (startIdx != idx) {
                        ret.Add(new Token(text.Substring(startIdx, idx - startIdx), line, src));
                    }
                    while (idx < text.Length && text[idx] != '\n') {
                        idx++;
                    }
                    idx++;
                    startIdx = idx;
                    line++;
                    continue;
                }

                /*多行注释*/
                if (mark == "；；" || mark == ";;") {
                    /*
                     * 发现当前是分号，处理前面的片段，然后一直找到换行
                     * 分号是注释标记，不进入语法解析
                     * 直接更新起点
                     */
                    if (startIdx != idx) {
                        ret.Add(new Token(text.Substring(startIdx, idx - startIdx), line, src));
                    }
                    idx+=2;
                    while (idx < text.Length ) {
                        if(idx < text.Length-1 && text[idx] == mark[0] && text[idx+1] == mark[0]) {
                            idx+=2;
                            break;
                        }else if (text[idx] == '\n') {
                            line++;
                        }
                        idx++;
                    }
                    startIdx = idx;
                    continue;
                }


                if (mark != "" && IsSymbol(mark)) {
                    /*
                     * 发现当前字符串位点以关键标记开头
                     * 如果是符号，则进行分割
                     * 但如果是中文关键字，那么有可能是变量名的一部分，不进行分割
                     * 所以中文关键字使用时前后需要有空格，或者前后是符号
                     */
                    if(startIdx != idx) {
                        /*处理前面的片段*/
                        ret.Add(new Token(text.Substring(startIdx, idx - startIdx), line, src));  
                    }

                    /*if (mark != "，" && mark != ",") {
                        *//*逗号不进入语法解析，仅做分割*//*
                        ret.Add(new Token(mark, line, src));
                    }*/
                    ret.Add(new Token(mark, line, src));
                    idx += mark.Length;
                    startIdx = idx;
                    continue;
                }
                idx++;
            }
            if(startIdx != idx) {
                /*遍历到结尾，把最后一个片段加入到结果列表*/
                ret.Add(new Token(text.Substring(startIdx, idx - startIdx), line, src));
            }


            /*处理负号和减法的歧义*/
            for(int i=0; i<ret.Count; i++) {
                if (ret[i].Str == "-" && ((i == 0 && ret.Count > 1) || ((i>0 && Marks.Contains(ret[i-1].Str) && i<ret.Count-1)) && ret[i-1].Str != "）" && ret[i-1].Str != ")")) {
                    
                    ret[i].Str = ret[i].Str + ret[i+1].Str;
                    ret.RemoveAt(i+1);
                    
                }else if (ret[i].Str == "，" || ret[i].Str == ",") {
                    ret.RemoveAt(i);
                    
                    if (i < ret.Count-1 && ret[i].Str == "-") {
                        ret[i].Str = ret[i].Str + ret[i+1].Str;
                        ret.RemoveAt(i+1);
                    } else {
                        i--;
                    }
                }else if (ret[i].Str == "~" && i>0 && i < ret.Count-1) {
                    ret[i-1].Str += ret[i+1].Str;
                    ret.RemoveAt(i);
                    ret.RemoveAt(i);
                    i--;
                }
            }

            return ret;
        }

        /*截取字符串*/
        public string TakeStr(string text, int idx) {
            if (text[idx] != '“' && text[idx] != '‘' && text[idx] != '"') {
                return "";
            }
            int startIdx = idx;
            idx++;
            if (text[startIdx] == '“') {
                while (idx < text.Length) {
                    /*发现换行，行号加1*/
                    if (text[idx] == '\n') {
                        line++;
                    }
                    /*发现转义标记，越过后一个字符*/
                    if (text[idx] == '\\') {
                        idx += 2;
                        continue;
                    }
                    /*发现闭合标记，截取字符串并返回*/
                    if (text[idx] == '”') {
                        return text.Substring(startIdx, idx-startIdx+1);
                    }
                    idx++;
                }
            } else if (text[startIdx] == '‘') {
                while (idx < text.Length) {
                    /*发现换行，行号加1*/
                    if (text[idx] == '\n') {
                        line++;
                    }
                    /*发现转义标记，越过后一个字符*/
                    if (text[idx] == '\\') {
                        idx += 2;
                        continue;
                    }
                    /*发现闭合标记，截取字符串并返回*/
                    if (text[idx] == '’') {
                        return text.Substring(startIdx, idx-startIdx+1);
                    }
                    idx++;
                }
            } else if (text[startIdx] == '"') {
                while (idx < text.Length) {
                    /*发现换行，行号加1*/
                    if (text[idx] == '\n') {
                        line++;
                    }
                    /*发现转义标记，越过后一个字符*/
                    if (text[idx] == '\\') {
                        idx += 2;
                        continue;
                    }
                    /*发现闭合标记，截取字符串并返回*/
                    if (text[idx] == '"') {
                        return text.Substring(startIdx, idx-startIdx+1);
                    }
                    idx++;
                }
            }

            if(idx < text.Length) {
                return text.Substring(idx);
            } else {
                return text;
            }
        }

        /*截取路径*/
        public string TakePath(string text, int idx) {
            if (text[idx] != '#' && text[idx] != '@') {
                return "";
            }
            string currMark = text[idx].ToString();
            int startIdx = idx;
            idx++;
            while (idx < text.Length) {
                if (text[idx] == '\n') {
                    //line++;
                    if(idx != startIdx) {
                        return text.Substring(startIdx, idx-startIdx);
                    }
                }

                if ((text[idx] == '【' || text[idx] == '[') && idx > 0 && text[idx-1]!='@') {
                    SkipArr(text, ref idx);
                    if (idx < text.Length && text[idx] == '\n') {
                        return text.Substring(startIdx, idx-startIdx);
                    }
                    continue;
                }
                if ((text[idx] == '｛' || text[idx] == '{') && idx > 0 && text[idx-1]=='@') {
                    SkipBrace(text, ref idx);
                    if (idx < text.Length && text[idx] == '\n') {
                        return text.Substring(startIdx, idx-startIdx);
                    }
                    continue;
                }

                string mark = StartWithMark(text, idx);
                if (char.IsWhiteSpace(text[idx]) || (mark != "" && IsSymbol(mark) )) {
                    return text.Substring(startIdx, idx-startIdx);
                }
                idx++;
            }

            if (idx < text.Length) {
                return text.Substring(startIdx, idx - startIdx);
            } else {
                return text.Substring(startIdx);
            }
        }

        /*判断是否是符号，包括英文符号和中文符号*/
        public static bool IsSymbol(string mark) {
            int n = mark[0];
            return 
                (n<127 && (n < 0x30
                || (n >= 0x3A && n <=0x40 )
                || (n >= 0x5B && n <= 0x60)
                || (n >= 0x7B && n < 0x7F)))
                || mark == "：" || mark == "“" || mark == "”"
                || mark == "【" || mark == "】"|| mark == "（"|| mark == "）"|| mark == "｛" || mark == "｝"
                || mark == "[" || mark == "]"|| mark == "("|| mark == ")"|| mark == "{" || mark == "}"
                || mark == "《" || mark == "》"|| mark == "，" || mark == "、";
        }

        /*判断是否是加减法符号*/
        public static bool IsAddMark(string mark) {
            foreach (var item in AddMarks) {
                if (mark == item) return true;
            }
            return false;
        }

        /*判断是否是乘除法符号*/
        public static bool IsMulMark(string mark) {
            foreach (var item in MulMarks) {
                if (mark == item) return true;
            }
            return false;
        }

        /*判断是否是比较符号*/
        public static bool IsCompareMark(string mark) {
            foreach (var item in CompareMarks) {
                if (mark == item) return true;
            }
            return false;
        }

        /*判断是否是逻辑运算符号*/
        public static bool IsLogicMark(string mark) {
            foreach (var item in LogicMarks) {
                if (mark == item) return true;
            }
            return false;
        }

        /*判断是否是设值符号*/
        public static bool IsSetMark(string mark) {
            foreach (var item in SetMarks) {
                if (mark == item) return true;
            }
            return false;
        }

        /*
         * 获取中缀符号的优先级
         * 越小的优先级越高
         */
        public static int GetOpLev(string mark) {
            if (IsSetMark(mark)) {
                return 5;
            } else if (IsLogicMark(mark)) {
                return 4;
            } else if (IsCompareMark(mark)) {
                return 3;
            }else if (IsAddMark(mark)) {
                return 2;
            }else if (IsMulMark(mark)) {
                return 1;
            }
            return 6;
        }

        /*
         * 获取中缀Expr列表中优先级最高的序号
         * 用于构建连续的中缀表达式
         */
        public static int GetHighestOpIndex(List<Expr> list) {
            int idx = 0;
            int min = 6;
            /*连续中缀表达式，每次移动2位*/
            for(int i=0; i< list.Count / 2; i++) {
                int pri = GetOpLev((string)list[i*2+1].Val);
                if (pri < min) {
                    idx = i*2+1;
                    min = pri;
                }
            }
            return idx;
        }

        /*判断是否是中缀标记*/
        public static bool IsOpMark(string mark) {
            return IsAddMark(mark) || IsMulMark(mark) || IsCompareMark(mark) || IsLogicMark(mark) || IsSetMark(mark);
        }

        /*
         * 判断字符串是否是数字的字面值
         * 返回找到的点的数量
         * 返回-1表示不是数字
         * 返回0表示是整数
         * 返回1表示是小数
         */
        public static int IsNumberStr(string s) {
            char[] cs = s.ToCharArray();
            int idx = 0;
            int dot = 0;

            if (s.Length == 0) {
                return -1;
            }
            if (s == "-") {
                return -1;
            }

            if (s.StartsWith('-')) {
                idx = 1;
            }

            while (idx < cs.Length) {
                if (cs[idx].Equals('.')) {
                    dot++;
                } else if (!char.IsNumber(cs[idx])) {
                    return -1;
                }

                idx++;
            }

            return dot;
        }

        /*
         * 对于路径类型的Expr
         * 进行切割
         * 区分出字符串类型的变量名
         * 和整数类型的索引序号
         */
        public List<string> SplitPath(string path) {
            List<string> ret = new List<string>();
            if(path.Length == 0) {
                return ret;
            }
            int startIdx = 0;
            int idx = 0;
            while(idx < path.Length) {
                if (path[idx] == '@' || path[idx] == '#') {                   
                    if(startIdx != idx) {
                        ret.Add(path[startIdx..idx]);
                        startIdx = idx;
                    }

                    if (idx < path.Length - 1 && (path[idx+1] == '【' || path[idx+1] == '[')) {
                        idx++;
                        SkipArr(path, ref idx, false);
                        ret.Add(path[startIdx..idx]);
                        startIdx = idx;
                        continue;
                    }
                    if (path[startIdx..].StartsWith("@｛") || path[startIdx..].StartsWith("@{")) {
                        idx++;
                        SkipBrace(path, ref idx, false);
                        ret.Add(path[(startIdx)..idx]);
                        startIdx = idx;
                        continue;
                    }
                } else if (path[idx] == '【' || path[idx] == '[') {
                    if (startIdx != idx) {
                        ret.Add(path[startIdx..idx]);
                        startIdx = idx;
                    }
                    SkipArr(path, ref idx, false);
                    ret.Add(path[startIdx..idx]);
                    startIdx = idx;
                    continue;
                }
                idx++;
            }
            if (startIdx != idx) {
                ret.Add(path[startIdx..]);
            }

            return ret;
        }





/**********************************************************************************************************************/




        /*解析代码字符串的方法*/
        public List<Expr> Parse(string inp, Ctx ctx, string src="标准输入") {
            try {
                /*先切割字符串，再生成Expr序列*/
                return MakeExprs(SliceText(inp, src), ctx);
            }catch(ParseException e) {
                /*解析过程中发生异常，对应语法错误，生成Err类型Expr*/
                return new List<Expr> { new Expr(TP.Err, e.Message, e.Line, e.Src) };
            }
            
        }


        /*将整个Token序列生成对应的Expr序列*/
        public List<Expr> MakeExprs(List<Token> tks, Ctx ctx, bool hasWord = false) {
            return MakeExprs(tks, 0, tks.Count, ctx, hasWord);
        }

        /*
         * 将Token序列生成对应的Expr序列
         * 指定起点和终点
         */
        public List<Expr> MakeExprs(List<Token> tks, int start, int end, Ctx ctx, bool hasWord = false) {
            List<Expr> ret = new List<Expr>();
            if(tks.Count == 0) {
                return ret;
            }
            int idx = start;
            Expr? preExpr = null;
            Expr? expr = null;
            while (idx < end) {
                /*生成一个Expr*/
                expr = MakeExpr(tks, ref idx, ctx, true, hasWord);

                /*一些Expr归属于父语句，在这里进行判断*/
                if (expr.Tp == TP.Elif || expr.Tp == TP.Else) {
                    /*
                     * 当前Expr对应再则语句或否则语句
                     * 那么前一个Expr必须是如果语句
                     * 把当前的Expr的list放到如果语句的list里
                     */
                    if(preExpr == null || preExpr.Tp != TP.If) {
                        throw new ParseException("如果...再则...否则语句语法错误", expr.Line, expr.Src);
                    }
                    if (expr.Tp == TP.Elif) {
                        preExpr.List!.Add(expr.List![0]);
                        preExpr.List!.Add(expr.List![1]);
                    } else if (expr.Tp == TP.Else) {
                        preExpr.List!.Add(expr.List![0]);
                    }
                    continue;
                }

                if (expr.Tp == TP.Finally) {
                    /*
                     * 当前Expr对应例行语句
                     * 那么前一个Expr必须是尝试语句
                     * 把当前的Expr放到尝试语句的list里
                     */
                    if (preExpr == null || preExpr.Tp != TP.Try) {
                        throw new ParseException("尝试...排查...例行语句语法错误", expr.Line, expr.Src);
                    }
                    preExpr.List!.Add(expr.Raw());
                    continue;
                }

                   
                ret.Add(expr);  
                preExpr = expr;

            }


            return ret;
        }


        /*
         * 这是生成单个Expr的方法
         * 是整个解析部分的核心
         * 在这里能够实现语法的设计
         * 主要根据当前Token的特征判断归属于哪一类表达式
         * 然后生成对应的Expr
         * 传入Token序列和当前的序号
         * 每生成一个Expr，序号向后移动
         * 便于遍历生成Expr序列
         * 
         * checkOp表示是否向后检查中缀表达式
         * 在生成一般表达式时需要向后检查
         * 但是在生成中缀表达式本身时，不应向后检查
         * 
         */
        public Expr MakeExpr(List<Token> tks, ref int idx, Ctx ctx, bool checkOp = true, bool hasWord = false) {
            /*边界检查，出现越界说明表达式不完整，语法有误*/
            if (idx >= tks.Count) {
                throw new ParseException("表达式不完整！！！", tks[tks.Count-1].Line, tks[tks.Count-1].Src);
            }
            /*这里tk为当前遍历到的Token*/
            var tk = tks[idx];
            /*定义要返回的Expr*/
            Expr? expr = null;

            /*首先是一些固定字面值的解析*/
            if (tk.Str == "空") {
                expr = new Expr(TP.None, 0, tk.Line, tk.Src);
                idx++;
            }

            if (tk.Str == "真") {
                expr = new Expr(TP.Bool, true, tk.Line, tk.Src);
                idx++;
            }

            if (tk.Str == "假") {
                expr = new Expr(TP.Bool, false, tk.Line, tk.Src);
                idx++;
            }

            if (tk.Str == "跳出") {
                expr = new Expr(TP.Break, 0, tk.Line, tk.Src);
                idx++;
            }

            if (tk.Str == "继续") {
                expr = new Expr(TP.Continue, 0, tk.Line, tk.Src);
                idx++;
            }

            /*取反语句*/
            if (tk.Str == "取反") {
                expr = new Expr(TP.Negate, 0, tk.Line, tk.Src);
                idx++;
                /*
                 * 取反是对后一个表达式的值取反
                 * 所以序号idx加1之后
                 * 再向后生成一个Expr
                 * 后面很多类似的操作
                 */
                expr.Val = MakeExpr(tks, ref idx, ctx);
            }

            /*
             * 元语句
             * 保留解析期产生的Expr类型
             * 避免在运行期直接被求解
             */
            if (tk.Str == "元") {
                idx++;
                expr = MakeExpr(tks, ref idx, ctx, false);
                expr = new Expr(TP.Meta, expr, tk.Line, tk.Src);
            }

            /*定义语句*/
            if (tk.Str == "定义") {
                idx++;
                /*向后取一个Expr作为返回值*/
                Expr result = MakeExpr(tks, ref idx, ctx);
                if(result.Tp == TP.Op) {
                    if(result.Str() == "=" || result.Str() == "：" || result.Str() == ":" || result.Str() == "为" || result.Str() == "设为") {
                        result.Val = "：";
                        expr = new Expr(TP.Dim, result, tk.Line, tk.Src);
                    } else {
                        throw new ParseException("定义语句错误", tk.Line, tk.Src);
                    }

                }else if(result.Tp == TP.Var || result.Tp == TP.Act ||  result.Tp == TP.Path) {
                    Expr dimOp = new Expr(TP.Op, "：", new List<Expr> { result, Expr.NoneExpr}, tk.Line, tk.Src);
                    expr = new Expr(TP.Dim, dimOp, tk.Line, tk.Src);
                } else {
                    throw new ParseException("定义语句错误", tk.Line, tk.Src);
                }
  
            }

            /*异步语句，表示定义的是一个异步函数*/
            if (tk.Str == "异步") {
                idx++;
                /*向后取一个定义函数类型的Expr*/
                expr = MakeExpr(tks, ref idx, ctx);
                if (expr.Tp != TP.Dim_func) {
                    throw new ParseException("定义函数语句错误", tk.Line, tk.Src);
                } else {
                    expr.Val = 1;
                }

            }

            /*等待语句*/
            if (tk.Str == "等待") {
                idx++;
                /*向后取一个要等待的任务类型Expr*/
                var task = MakeExpr(tks, ref idx, ctx);
                expr = new Expr(TP.Wait, task, tk.Line, tk.Src);

            }

            /*
             * Token以#号开头，有两种可能
             * 一种是单个变量名，另一种是路径
             */
/*            if (tk.str.StartsWith("#") && tk.str != "#") {
                *//*expr = new Expr(TP.Var, tk);
                idx++;*/

                /*尝试分割路径*//*
                List<string> list = SplitPath(tk.str);
                if (list.Count == 1) {
                    *//*分割后只有1个路径，说明是单个变量名*//*
                    expr = new Expr(TP.Var, tk.str, tk.line, tk.src);
                    idx++;
                } else {
                    *//*先假设是变量路径*//*
                    expr = new Expr(TP.Var_path, 0, new List<Expr>(), tk.line, tk.src);
                    foreach (var item in list) {
                        *//*遍历每个路径值，可能是字符串，也可能是整数类型的序号*//*
                        if (item.StartsWith("#【") && item.EndsWith("】")) {
                            expr.list!.Add(new Expr(TP.Arr, 0, Parse(item[2..(item.Length-1)], ctx)));
                        } else if (item.StartsWith("【") && item.EndsWith("】")) {
                            expr.list!.Add(new Expr(TP.Args, 0, Parse(item[1..(item.Length-1)], ctx)));
                        } else {
                            int dot = IsNumberStr(item[1..]);
                            if (dot == 0) {
                                expr.list!.Add(new Expr(TP.Int, int.Parse(item[1..]), tk.line, tk.src));
                            } else {
                                expr.list!.Add(new Expr(TP.Str, item, tk.line, tk.src));
                            }
                        }                       
                    }
                    idx++;
                    if (idx < tks.Count && (list[list.Count-1].StartsWith("@") || expr.list![expr.list!.Count-1].tp == TP.Int)) {
                        *//*
                         * 如果路径的最后一个以@开头
                         * 那么是函数路径
                         * 还要向后检查，是否是函数调用
                         *//*
                        if (tks[idx].str == "【") {
                            *//*
                             * 后面加的是中括号
                             * 那么中括号后面里是函数调用传入的参数列表
                             *//*
                            expr.tp = TP.Act_path;
                            Expr args = MakeExpr(tks, ref idx, ctx, false);
                            expr.tp = TP.Call_act_path;
                            expr.val = args.list!;
                        } else if (tks[idx].str == "、") {
                            *//*
                             * 后面加的是顿号
                             * 那么中括号后面里是函数调用传入的单个参数
                             *//*
                            expr.tp = TP.Act_path;
                            idx++;
                            Expr arg = MakeExpr(tks, ref idx, ctx);
                            expr.tp = TP.Call_act_path;
                            expr.val = new List<Expr> { arg };
                        }
                    }
                }
            }*/

            /*
             * Token以@号开头
             * 表示函数或函数调用
             */
/*            if (tk.str.StartsWith("@") && tk.str != "@") {
                expr = new Expr(TP.Act, tk.str, tk.line, tk.src);
                idx++;
                *//*向后检查是否是函数调用*//*
                if (idx<tks.Count && tks[idx].str == "【") {
                    *//*
                    * 后面加的是中括号
                    * 那么中括号后面里是函数调用传入的参数列表
                    *//*
                    Expr args = MakeExpr(tks, ref idx, ctx, false);
                    expr.tp = TP.Call_act;
                    expr.list = args.list;
                } else if (idx<tks.Count && tks[idx].str == "、") {
                    *//*
                    * 后面加的是顿号
                    * 那么中括号后面里是函数调用传入的单个参数
                    *//*
                    idx++;
                    Expr arg = MakeExpr(tks, ref idx, ctx);
                    expr.tp = TP.Call_act;
                    expr.list = new List<Expr> { arg };
                }
            }
*/



            /*
                * Token以0x开头
                * 表示二进制类型的Expr
                * 把0x后面的字符串转为字节数组
                */
            if (tk.Str.StartsWith("0x")) {
                expr = new Expr(TP.Bin, StrToToHexByte(tk.Str[2..]), tk.Line, tk.Src);
                idx++;
            }

            /*Token以“开头，说明是字符串类型*/
            if (tk.Str.StartsWith("“") || tk.Str.StartsWith("‘") || tk.Str.StartsWith("\"")) {
                expr = new Expr(TP.Str, RawStr(tk.Str.Substring(1, tk.Str.Length-2)), tk.Line, tk.Src);
                idx++;
            }

            /*Token以【开头，说明是数组类型*/
            if (tk.Str.StartsWith("【") || tk.Str.StartsWith("[")) {
                expr = new Expr(TP.Block, 0, tk.Line, tk.Src);
                /*越过起始标记*/
                int start = idx+1;
                /*找到数组的结尾*/
                SkipArr(tks, ref idx);
                int end = idx;
                if (end <= start + 1) {
                    /*数组为空*/
                    expr.List = new List<Expr>();
                } else {
                    /*传入起止点，把数组内部的Token序列转为Expr序列*/
                    expr.List = MakeExprs(tks, start, end-1, ctx);
                }
            }

            /*Token以【开头，说明是圆括号类型*/
            if (tk.Str.StartsWith("（") || tk.Str.StartsWith("(")) {
                expr = new Expr(TP.Paren, 0, tk.Line, tk.Src);
                /*越过起始标记*/
                int start = idx+1;
                /*找到圆括号组的结尾*/
                SkipParen(tks, ref idx);
                int end = idx;
                if (end <= start + 1) {
                    /*圆括号为空*/
                    expr.List = new List<Expr>();
                } else {
                    /*传入起止点，把圆括号内部的Token序列转为Expr序列*/
                    expr.List = MakeExprs(tks, start, end-1, ctx);
                }
            }

            /*Token以【开头，说明是大括号类型*/
            if (tk.Str.StartsWith("｛") || tk.Str.StartsWith("{")) {
                expr = new Expr(TP.Brace, ctx, tk.Line, tk.Src);
                /*越过起始标记*/
                int start = idx+1;
                /*找到大括号组的结尾*/
                SkipBrace(tks, ref idx);
                int end = idx;
                if (end <= start + 1) {
                    /*大括号为空*/
                    expr.List = new List<Expr>();
                } else {
                    /*传入起止点，把大括号内部的Token序列转为Expr序列*/
                    expr.List = MakeExprs(tks, start, end-1, ctx);
                }
            }

            /*Token以《开头，说明是标签类型*/
            if (tk.Str.StartsWith("《")) {
                Tag tag = new Tag();
                expr = new Expr(TP.Tag, tag, tk.Line, tk.Src);
                /*越过起始标记*/
                int start = idx+1;
                if(start >= tks.Count-1 || tks[start].Str == "》") {
                    throw new ParseException("未闭合的标签", tk.Line, tk.Src);
                }
                string tagName = tks[start].Str;
                if (tagName.StartsWith("#")) {
                    tag.Name = new Expr(TP.Var, tagName);
                } else {
                    tag.Name = new Expr(TP.Str, tagName);
                }

                /*找到数组的结尾*/
                SkipTag(tks, ref idx);
                int end = idx;

                List<Expr> list = MakeExprs(tks, start+1, end-1, ctx);
                for(int i=0; i<list.Count; i++) {
                    if (list[i].Tp == TP.Op && (list[i].Str() == "：" || list[i].Str() == "："|| list[i].Str() == "=")) {
                        tag.Attrs.Add(list[i]);
                    }else if (list[i].Tp == TP.Block) {
                        tag.Children = list[i];
                    }
                }

            }



            /*如果语句*/
            if (tk.Str == "如果") {
                idx++;
                /*向后取一个Expr作为条件判断表达式*/
                Expr cond = MakeExpr(tks, ref idx, ctx);
                /*再向后取一个Expr作为条件为真的执行体*/
                Expr body = MakeExpr(tks, ref idx, ctx);
                if (body.Tp != TP.Brace) {
                    throw new ParseException("如果语句语法错误", tk.Line, tk.Src);
                }
                expr = new Expr(TP.If, "如果", new List<Expr>(), tk.Line, tk.Src);
                expr.List!.Add(cond);
                expr.List!.Add(body);
            }

            /*再则语句*/
            if (tk.Str == "再则") {
                idx++;
                Expr cond = MakeExpr(tks, ref idx, ctx);
                Expr body = MakeExpr(tks, ref idx, ctx);
                if (body.Tp != TP.Brace) {
                    throw new ParseException("再则语句语法错误", tk.Line, tk.Src);
                }
                expr = new Expr(TP.Elif, "再则", new List<Expr>(), tk.Line, tk.Src);
                expr.List!.Add(cond);
                expr.List!.Add(body);
            }

            /*否则语句*/
            if (tk.Str == "否则") {
                idx++;
                Expr body = MakeExpr(tks, ref idx, ctx);
                if (body.Tp != TP.Brace) {
                    throw new ParseException("再则语句语法错误", tk.Line, tk.Src);
                }
                expr = new Expr(TP.Else, "否则", new List<Expr>(), tk.Line, tk.Src);
                expr.List!.Add(body);
            }

            /*当语句*/
            if (tk.Str == "当") {
                idx++;
                expr = new Expr(TP.While, "当", new List<Expr>(), tk.Line, tk.Src);
                Expr we = MakeExpr(tks, ref idx, ctx);
                expr.List!.Add(we);
                we = MakeExpr(tks, ref idx, ctx);
                expr.List!.Add(we);
                /*
                 * 当语句包含while和for两种情况
                 * 如果向后取的第二个Expr就是大括号类型
                 * 那么就是while语句
                 * 否则应该是for语句
                 */
                if (we.Tp == TP.Brace) {
                    return expr;
                }
                we = MakeExpr(tks, ref idx, ctx);
                expr.List!.Add(we);
                we = MakeExpr(tks, ref idx, ctx);
                expr.List!.Add(we);
                if (we.Tp != TP.Brace) {
                    throw new ParseException("当语句语法错误", tk.Line, tk.Src);
                }

            }

            /*遍历语句*/
            if (tk.Str == "遍历") {
                idx++;
                /*
                 * 语法设计是遍历...为...
                 * 所以向后的第一个Expr需要是Op类型
                 * 支持使用关键字 为 或者 = 设置迭代变量名
                 */
                Expr cond = MakeExpr(tks, ref idx, ctx);
                if(cond.Tp == TP.Op && (cond.Str() == "=" || cond.Str() == "为") && cond.List![1].Tp == TP.Var) {
                    /*再向后取一个Expr作为循环执行体*/
                    Expr body = MakeExpr(tks, ref idx, ctx);
                    if(body.Tp != TP.Brace) {
                        throw new ParseException("遍历语句语法错误", tk.Line, tk.Src);
                    }
                    expr = new Expr(TP.Foreach, 0, new List<Expr>(), tk.Line, tk.Src);
                    expr.List!.Add(cond.List![0]);
                    expr.List!.Add(cond.List![1]);
                    expr.List!.Add(body);
                } else {
                    throw new ParseException("遍历语句语法错误", tk.Line, tk.Src);
                }
            }

            /*执行...直到 语句*/
            if (tk.Str == "执行") {
                idx++;
                Expr body = MakeExpr(tks, ref idx, ctx);
                /*先向后取一个Expr作为循环执行体*/
                if(body.Tp != TP.Brace) {
                    throw new ParseException("执行...直到语句语法错误", tk.Line, tk.Src);
                }
                if (tks[idx].Str != "直到") {
                    throw new ParseException("执行...直到语句语法错误", tk.Line, tk.Src);
                }
                idx++;
                /*再向后取一个Expr作为循环条件表达式*/
                Expr cond = MakeExpr(tks, ref idx, ctx);
                expr = new Expr(TP.Until, "直到", new List<Expr>(), tk.Line, tk.Src);
                expr.List!.Add(body);
                expr.List!.Add(cond);
            }

            /*返回语句*/
            if (tk.Str == "返回") {
                idx++;
                /*向后取一个Expr作为返回值*/
                Expr result = MakeExpr(tks, ref idx, ctx);
                expr = new Expr(TP.Return, result, tk.Line, tk.Src);
            }

            /*尝试...排查...例行 语句*/
            if (tk.Str == "尝试") {
                idx++;
                /*向后取一个Expr作为执行体*/
                Expr body = MakeExpr(tks, ref idx, ctx);
                if (body.Tp != TP.Brace) {
                    throw new ParseException(" 尝试...排查语句语法错误", tk.Line, tk.Src);
                }
                
                expr = new Expr(TP.Try, "尝试", new List<Expr>(), tk.Line, tk.Src);
                expr.List!.Add(body);

                if (idx < tks.Count && tks[idx].Str == "排查") {
                    idx++;
                    if(idx < tks.Count) {
                        /*向后取一个Expr作为绑定异常的变量名*/
                        Expr eVar = MakeExpr(tks, ref idx, ctx);
                        if (eVar.Tp == TP.Var) {
                            /*向后取一个Expr作为发生异常时的执行体*/
                            Expr eHandler = MakeExpr(tks, ref idx, ctx);
                            if (eHandler.Tp != TP.Brace) {
                                throw new ParseException("尝试...排查语句语法错误", tk.Line, tk.Src);
                            }
                            expr.List!.Add(eVar);
                            expr.List!.Add(eHandler);
                        }

                    }

                } else {
                    expr.List!.Add(Expr.NoneExpr);
                    expr.List!.Add(Expr.NoneExpr);
                } 
                
            }

            /*例行语句*/
            if (tk.Str == "例行") {
                idx++;
                /*向后取一个Expr作为执行体*/
                Expr body = MakeExpr(tks, ref idx, ctx);
                if (body.Tp != TP.Brace) {
                    throw new ParseException("例行语句语法错误", tk.Line, tk.Src);
                }
                expr = new Expr(TP.Finally, body, tk.Line, tk.Src);
            }

            /*返回语句*/
            if (tk.Str == "抛出") {
                idx++;
                /*向后取一个Expr作为返回值*/
                Expr result = MakeExpr(tks, ref idx, ctx);
                expr = new Expr(TP.Throw, result, tk.Line, tk.Src);
            }

            /*重复语句*/
            if (tk.Str == "重复") {
                idx++;
                /*向后取一个Expr作为重复次数*/
                Expr times = MakeExpr(tks, ref idx, ctx);
                /*再向后取一个Expr作为执行体*/
                Expr body = MakeExpr(tks, ref idx, ctx);
                if (body.Tp != TP.Brace) {
                    throw new ParseException("重复语句语法错误", tk.Line, tk.Src);
                }
                expr = new Expr(TP.Repeat, 0, new List<Expr> { times, body}, tk.Line, tk.Src);
            }

            /*返回语句*/
            if (tk.Str == "默认") {
                expr = new Expr(TP.Default, 0, tk.Line, tk.Src);
                idx++;
            }

            /*匹配语句*/
            if (tk.Str == "匹配") {
                idx++;
                /*向后取一个Expr作为重复次数*/
                Expr target = MakeExpr(tks, ref idx, ctx);
                /*再向后取一个Expr作为执行体*/
                Expr body = MakeExpr(tks, ref idx, ctx);
                if (body.Tp != TP.Brace) {
                    throw new ParseException("匹配语句语法错误", tk.Line, tk.Src);
                }

                List<Expr> caseList = new List<Expr>();
                List<Expr>? caseGroup = null;
                Expr? defaultBrace = null;
                for(int i = 0; i<body.List!.Count; i++) {
                    Expr item = body.List![i];
                    if ((caseGroup == null || caseGroup.Count == 0) && item.Tp == TP.Brace) {
                        throw new ParseException("匹配语句语法错误，没有给出匹配值", tk.Line, tk.Src);
                    }
                    if (caseGroup == null) {
                        caseGroup = new List<Expr>();
                    }
                    if (item.Tp == TP.Brace) {
                        caseList.Add(new Expr(TP.Arr, 0, caseGroup!));
                        caseList.Add(item); 
                        caseGroup = null;
                    } else if (item.Tp == TP.Default) {
                        if (caseGroup.Count > 0) {
                            throw new ParseException("匹配语句语法错误，匹配值与默认关键字不能组合", tk.Line, tk.Src);
                        }
                        if (i<body.List!.Count-1 && body.List![i+1].Tp == TP.Brace) {
                            defaultBrace = body.List![i+1];
                            i++;
                        } else {
                            throw new ParseException("匹配语句语法错误，没有给出默认匹配的代码块", tk.Line, tk.Src);
                        }
                    } else {
                        caseGroup.Add(item);
                    }
                }
                if(caseGroup != null && caseGroup.Count > 0) {
                    throw new ParseException("匹配语句语法错误，缺少匹配的代码块", tk.Line, tk.Src);
                }
                if(defaultBrace != null) {
                    caseList.Add(new Expr(TP.Default, 0));
                    caseList.Add(defaultBrace);
                }

                expr = new Expr(TP.Match, target, caseList, tk.Line, tk.Src);
            }


            if (tk.Str == "@" && idx < tks.Count-1) {
                if (tks[idx+1].Str == "【" || tks[idx+1].Str == "[") {
                    /*如果Token序列以@【开头，说明是定义函数,调用构建定义函数Expr的方法*/
                    expr = BuileDimFunc(tks, ref idx, ctx);
                } else if (tks[idx+1].Str == "｛" || tks[idx+1].Str == "{") {
                    /*如果Token序列以@｛开头，说明是定义函数,调用构建定义函数Expr的方法*/
                    expr = BuileDimObj(tks, ref idx, ctx);
                }
                
            }


            if ((tk.Str.StartsWith("#") && tk.Str != "#") || (tk.Str.StartsWith("@") && tk.Str != "@")) {
                /*尝试分割路径*/
                List<string> list = SplitPath(tk.Str);
                if (list.Count == 1) {
                    /*分割后只有1个路径，说明是单个变量名*/
                    if (tk.Str.StartsWith("#")) {
                        expr = new Expr(TP.Var, tk.Str, tk.Line, tk.Src);
                        idx++;
                    } else if (tk.Str.StartsWith("@｛") || tk.Str.StartsWith("@{")) {
                        expr = BuileDimObj(tk, ctx);
                        idx++;
                    } else {
                        expr = new Expr(TP.Act, tk.Str, tk.Line, tk.Src);
                        idx++;
                        //*向后检查是否是函数调用*//
                        if (idx<tks.Count && tks[idx].Str == "、") {

                            /*后面的是顿号
                            那么顿号后面里是函数调用传入的参数*/
                            List<Expr> argList = new List<Expr>();
                            while(idx < tks.Count && tks[idx].Str == "、") {
                                idx++;
                                Expr arg = MakeExpr(tks, ref idx, ctx);
                                argList.Add(arg);
                            }
                            
                            expr.Tp = TP.Path;
                            expr.List = new List<Expr> {
                                new Expr(TP.Str, tk.Str, tk.Line, tk.Src),
                                new Expr(TP.Args, 0, argList, tk.Line, tk.Src),
                            };
                        }
                    }
                    
                } else {

                    /*设定为路径*/
                    expr = new Expr(TP.Path, 0, new List<Expr>(), tk.Line, tk.Src);
                    int i = 0;
                    foreach (var item in list) {
                        /*遍历每个路径值，可能是字符串，也可能是整数类型的序号*/
                        if ((item.StartsWith("#【") && item.EndsWith("】")) || (item.StartsWith("#[") && item.EndsWith("]"))) {
                            expr.List!.Add(new Expr(TP.Block, 0, Parse(item[2..(item.Length-1)], ctx)));
                        } else if ((item.StartsWith("【") && item.EndsWith("】")) || (item.StartsWith("[") && item.EndsWith("]"))) {
                            expr.List!.Add(new Expr(TP.Args, 0, Parse(item[1..(item.Length-1)], ctx)));
                        } else if ((item.StartsWith("@｛") && item.EndsWith("｝")) || (item.StartsWith("@{") && item.EndsWith("}"))) {
                            if(i == 0) {
                                expr.List!.Add(BuileDimObj(item, ctx, tk));
                            } else {
                                expr.List!.Add(new Expr(TP.Brace, 0, Parse(item[2..(item.Length-1)], ctx)));
                            }
                        } else {
                            int dot = IsNumberStr(item[1..]);
                            if (dot == 0) {
                                expr.List!.Add(new Expr(TP.Int, int.Parse(item[1..]), tk.Line, tk.Src));
                            } else {
                                expr.List!.Add(new Expr(TP.Str, item, tk.Line, tk.Src));
                            }
                        }
                        i++;
                    }

                    idx++;
                    if (idx < tks.Count && tks[idx].Str == "、") {
                        idx++;
                        expr.List!.Add(new Expr(TP.Args, 0, new List<Expr> { MakeExpr(tks, ref idx, ctx) }, tk.Line, tk.Src));
                    }

                }

            }




            /*
             * 最后，不符合预设句式的Token都会进入这段逻辑
             * 主要是数字
             */
            if (expr == null) {
                int dot = IsNumberStr(tk.Str);
                if(dot == 0) {
                    expr = new Expr(TP.Int, int.Parse(tk.Str), tk.Line, tk.Src);
                }else if(dot == 1) {
                    expr = new Expr(TP.Float, decimal.Parse(tk.Str), tk.Line, tk.Src);
                } else {
                    /*
                     * 前面的逻辑会把关键字都过滤掉
                     * 理论上进入这里的都是语法上无法识别的元素
                     */
                    if (!KeyMarks.Contains(tk.Str)) {
                        if (hasWord) {
                            expr = new Expr(TP.Word, tk.Str, tk.Line, tk.Src);
                        } else {
                            throw new ParseException("无法识别的语法元素（" + tk.Str + "）", tk.Line, tk.Src);
                        }

                    } else {
                        expr = new Expr(TP.Word, tk.Str, tk.Line, tk.Src);
                    }
                    
                }
                
                idx++;
            }

            /*如果开启向后检查是否是中缀表达式，并且后面还有Token*/
            if (checkOp && idx < tks.Count) {
                var next = tks[idx];
                if (IsOpMark(next.Str)) {
                    /*发现后一个Token是中缀标记，调用构建中缀表达式的方法*/
                    expr = BuileOpExpr(tks, ref idx, expr!, ctx, hasWord);

                }
            }

            /*返回生成的Expr*/
            return expr!;
        }


        /*越过圆括号，或是查找圆括号的结尾*/
        public void SkipParen(List<Token> tks, ref int idx) {
            if(idx < tks.Count) {
                if (tks[idx].Str == "（") {
                    /*定义圆括号层数*/
                    int floor = 1;
                    idx++;
                    while(idx < tks.Count) {
                        if (tks[idx].Str == "（") {
                            floor++;
                        }
                        if (tks[idx].Str == "）") {
                            floor--;
                        }
                        idx++;
                        /*当定义圆括号层数为0时，圆括号闭合*/
                        if (floor == 0) {
                            return;
                        }
                    }

                } else if (tks[idx].Str == "(") {
                    /*定义圆括号层数*/
                    int floor = 1;
                    idx++;
                    while (idx < tks.Count) {
                        if (tks[idx].Str == "(") {
                            floor++;
                        }
                        if (tks[idx].Str == ")") {
                            floor--;
                        }
                        idx++;
                        /*当定义圆括号层数为0时，圆括号闭合*/
                        if (floor == 0) {
                            return;
                        }
                    }
                }
            }
        }

        /*越过数组，或是查找数组的结尾*/
        public void SkipArr(List<Token> tks, ref int idx) {
            if (idx < tks.Count) {
                if (tks[idx].Str == "【") {
                    /*定义数组层数*/
                    int floor = 1;
                    idx++;
                    while (idx < tks.Count) {
                        if (tks[idx].Str == "【") {
                            floor++;
                        }
                        if (tks[idx].Str == "】") {
                            floor--;
                        }
                        idx++;
                        /*当定义数组层数为0时，数组闭合*/
                        if (floor == 0) {
                            return;
                        }
                    }

                }else if (tks[idx].Str == "[") {
                    /*定义数组层数*/
                    int floor = 1;
                    idx++;
                    while (idx < tks.Count) {
                        if (tks[idx].Str == "[") {
                            floor++;
                        }
                        if (tks[idx].Str == "]") {
                            floor--;
                        }
                        idx++;
                        /*当定义数组层数为0时，数组闭合*/
                        if (floor == 0) {
                            return;
                        }
                    }
                }
            }
        }

        /*越过数组，或是查找数组的结尾，针对字符串*/
        public void SkipArr(string text, ref int idx, bool addLine=true) {
            if (idx < text.Length) {
                if (text[idx] == '【') {
                    /*定义数组层数*/
                    int floor = 1;
                    idx++;
                    while (idx < text.Length) {
                        if (addLine && text[idx] == '\n') {
                            line++;
                        }

                        if (text[idx] == '“' || text[idx] == '‘' ||  text[idx] == '"') {
                            string str = TakeStr(text, idx);
                            idx += str.Length;
                            continue;
                        }

                        if (text[idx] == '【') {
                            floor++;
                        }
                        if (text[idx] == '】') {
                            floor--;
                        }
                        idx++;
                        /*当定义数组层数为0时，数组闭合*/
                        if (floor == 0) {
                            return;
                        }
                    }

                }else if (text[idx] == '[') {
                    /*定义数组层数*/
                    int floor = 1;
                    idx++;
                    while (idx < text.Length) {
                        if (addLine && text[idx] == '\n') {
                            line++;
                        }

                        if (text[idx] == '“' || text[idx] == '‘' ||  text[idx] == '"') {
                            string str = TakeStr(text, idx);
                            idx += str.Length;
                            continue;
                        }

                        if (text[idx] == '[') {
                            floor++;
                        }
                        if (text[idx] == ']') {
                            floor--;
                        }
                        idx++;
                        /*当定义数组层数为0时，数组闭合*/
                        if (floor == 0) {
                            return;
                        }
                    }
                }
            }
        }


        /*越过大括号，或是查找大括号的结尾*/
        public void SkipBrace(List<Token> tks, ref int idx) {
            if (idx < tks.Count) {
                if (tks[idx].Str == "｛") {
                    /*定义大括号层数*/
                    int floor = 1;
                    idx++;
                    while (idx < tks.Count) {
                        if (tks[idx].Str == "｛") {
                            floor++;
                        }
                        if (tks[idx].Str == "｝") {
                            floor--;
                        }
                        idx++;
                        /*当定义大括号层数为0时，大括号闭合*/
                        if (floor == 0) {
                            return;
                        }
                    }

                }else if (tks[idx].Str == "{") {
                    /*定义大括号层数*/
                    int floor = 1;
                    idx++;
                    while (idx < tks.Count) {
                        if (tks[idx].Str == "{") {
                            floor++;
                        }
                        if (tks[idx].Str == "}") {
                            floor--;
                        }
                        idx++;
                        /*当定义大括号层数为0时，大括号闭合*/
                        if (floor == 0) {
                            return;
                        }
                    }
                }
            }
        }

        /*越过大括号，或是查找大括号的结尾，针对字符串*/
        public void SkipBrace(string text, ref int idx, bool addLine = true) {
            if (idx < text.Length) {
                if (text[idx] == '｛') {
                    /*定义大括号层数*/
                    int floor = 1;
                    idx++;
                    while (idx < text.Length) {
                        if (addLine && text[idx] == '\n') {
                            line++;
                        }

                        if (text[idx] == '“' || text[idx] == '‘' ||  text[idx] == '"') {
                            string str = TakeStr(text, idx);
                            idx += str.Length;
                            continue;
                        }

                        if (text[idx] == '｛') {
                            floor++;
                        }
                        if (text[idx] == '｝') {
                            floor--;
                        }
                        idx++;
                        /*当定义数组层数为0时，数组闭合*/
                        if (floor == 0) {
                            return;
                        }
                    }

                }else if (text[idx] == '{') {
                    /*定义大括号层数*/
                    int floor = 1;
                    idx++;
                    while (idx < text.Length) {
                        if (addLine && text[idx] == '\n') {
                            line++;
                        }

                        if (text[idx] == '“' || text[idx] == '‘' ||  text[idx] == '"') {
                            string str = TakeStr(text, idx);
                            idx += str.Length;
                            continue;
                        }

                        if (text[idx] == '{') {
                            floor++;
                        }
                        if (text[idx] == '}') {
                            floor--;
                        }
                        idx++;
                        /*当定义数组层数为0时，数组闭合*/
                        if (floor == 0) {
                            return;
                        }
                    }
                }
            }
        }


        /*越过标签，或是查找标签的结尾*/
        public void SkipTag(List<Token> tks, ref int idx) {
            if (idx < tks.Count) {
                if (tks[idx].Str == "《") {
                    /*定义数组层数*/
                    int floor = 1;
                    idx++;
                    while (idx < tks.Count) {
                        if (tks[idx].Str == "《") {
                            floor++;
                        }
                        if (tks[idx].Str == "》") {
                            floor--;
                        }
                        idx++;
                        /*当定义数组层数为0时，数组闭合*/
                        if (floor == 0) {
                            return;
                        }
                    }

                }
            }
        }


        /*越过中缀表达式，或是查找中缀表达式的结尾*/
        public void SkipOpExpr(List<Token> tks, ref int idx) {
            if(idx < tks.Count - 1) {
                if (IsOpMark(tks[idx+1].Str)) {
                    idx++;
                    /*有可能是连续的中缀表达式*/
                    while (idx < tks.Count && IsOpMark(tks[idx].Str)) {
                        idx++;
                        /*碰到集合，要先越过集合*/
                        if (tks[idx].Str == "（" || tks[idx].Str == "(") {
                            SkipParen(tks, ref idx);
                            continue;
                        }
                        if (tks[idx].Str == "【" || tks[idx].Str == "[") {
                            SkipArr(tks, ref idx);
                            continue;
                        }
                        if (tks[idx].Str == "｛" || tks[idx].Str == "{") {
                            SkipBrace(tks, ref idx);
                            continue;
                        }
                        idx++;
                    }
                }
            }
        }
        

        /*构建中缀表达式*/
        public Expr BuileOpExpr(List<Token> tks, ref int idx, Expr expr, Ctx ctx, bool hasWord) {
            /*定义预处理后得到的表达式列表*/
            List<Expr> preList = new List<Expr> {expr};
            while (idx < tks.Count && IsOpMark(tks[idx].Str)) {
                /*预处理列表中加入中缀类型的Expr*/
                preList.Add(new Expr(TP.Op, tks[idx].Str, new List<Expr>(), tks[idx].Line, tks[idx].Src));
                idx++;
                /*预处理列表中加入中缀后的运算数*/
                preList.Add(MakeExpr(tks, ref idx, ctx, false, hasWord));
            }

            /*把连续的中缀表达式合并成1个*/
            while(preList.Count > 1) {
                /*
                 * 每次从预处理列表中找出优先级最高的中缀运算
                 * 把最高优先级的中缀运算Expr左右两边的Expr作为运算数
                 * 放到中缀Expr的list中
                 */
                int highest = GetHighestOpIndex(preList);
                Expr hExpr = preList[highest];
                hExpr.List!.Add(preList[highest-1]);
                hExpr.List!.Add(preList[highest+1]);
                preList.RemoveAt(highest-1);
                preList.RemoveAt(highest);
            }

            /*最后只剩一个中缀Expr*/
            return preList[0];
        }


        /*构建定义函数的Expr*/
        public Expr BuileDimFunc(List<Token> tks, ref int idx, Ctx ctx) {
            idx++;
            int startIdx = idx;
            /*越过【】，作为参数列表*/
            SkipArr(tks, ref idx);
            int pEnd = idx;
            /*参数列表后面必须是大括号，作为执行体*/
            if(pEnd >= tks.Count || (tks[pEnd].Str != "｛" && tks[pEnd].Str != "{")) {
                throw new ParseException("定义函数语句语法错误", tks[startIdx].Line, tks[startIdx].Src);
            }
            /*创建返回的定义函数Expr*/
            Expr ret = new Expr(TP.Dim_func, 0, new List<Expr>(), tks[startIdx].Line, tks[startIdx].Src);
            /*根据之前找到的参数列表起止位置，生成参数列表，加入list*/
            ret.List!.Add(new Expr(TP.Block, 0, MakeExprs(tks, startIdx+1, pEnd-1, ctx)));

            startIdx = pEnd+1;
            SkipBrace(tks, ref idx);
            int bEnd = idx;
            /*根据之前找到的执行体起止位置，生成执行体，加入list*/
            ret.List!.Add(new Expr(TP.Brace, 0, MakeExprs(tks, startIdx, bEnd-1, ctx), tks[startIdx].Line, tks[startIdx].Src));
            
            return ret;
        }

        /*构建定义对象的Expr*/
        public Expr BuileDimObj(List<Token> tks, ref int idx, Ctx ctx) {
            idx++;
            int startIdx = idx;
            SkipBrace(tks, ref idx);
            int bEnd = idx;
            /*｛｝大括号内的是对象定义*/
            Expr ret = new Expr(TP.Dim_obj, 0, MakeExprs(tks, startIdx+1, bEnd-1, ctx), tks[startIdx].Line, tks[startIdx].Src);

            return ret;
        }

        /*构建定义对象的Expr*/
        public Expr BuileDimObj(Token tk, Ctx ctx) {
            
            Expr ret = new Expr(TP.Dim_obj, 0, Parse(tk.Str[2..(tk.Str.Length-1)], ctx, tk.Src), tk.Line, tk.Src);

            return ret;
        }

        /*构建定义对象的Expr*/
        public Expr BuileDimObj(string str, Ctx ctx, Token tk) {

            Expr ret = new Expr(TP.Dim_obj, 0, Parse(str[2..(str.Length-1)], ctx, tk.Src), tk.Line, tk.Src);

            return ret;
        }



        /*把字符串的字面值，转义得到原始的字符串*/
        public static string RawStr(string str) {
            string s = str;
            int i = 0;
            while (i < s.Length) {
                if (s[i] == '\\' && i < s.Length-1) {
                    s = s[0..i] + (Tranfer2char(s[i..(i+2)]) ?? s[i+1]) + s[(i+2)..];
                }
                i++;
            }
            return s;
        }

        /*格式化字符串的字面值，添加转义*/
        public static string FormStr(string str) {
            string s = "";
            char[] chars = str.ToCharArray();
            int i = 0;
            int startIdx = i;
            while (i < chars.Length) {
                string? tranfer = Char2tranfer(chars[i]);
                if (tranfer != null) {
                    s += str[startIdx..i] + tranfer;
                    startIdx = i+1;
                }
                i++;
            }
            if (startIdx < i) {
                s += str[startIdx..i];
            }
            return s;
        }

        public static char? Tranfer2char(string str) {
            foreach (var item in transferChar) {
                if (item.Item1 == str) {
                    return item.Item2;
                }
            }
            return null;
        }

        public static string? Char2tranfer(char c) {
            foreach (var item in transferChar) {
                if (item.Item2 == c) {
                    return item.Item1;
                }
            }
            return null;
        }




        private string StringToHexString(string s, Encoding encode) {
            byte[] b = encode.GetBytes(s);//按照指定编码将string编程字节数组
            string result = string.Empty;
            for (int i = 0; i < b.Length; i++)//逐字节变为16进制字符，以%隔开
            {
                result += "%"+Convert.ToString(b[i], 16);
            }
            return result;
        }
        private string HexStringToString(string hs, Encoding encode) {
            //以%分割字符串，并去掉空字符
            string[] chars = hs.Split(new char[] { '%' }, StringSplitOptions.RemoveEmptyEntries);
            byte[] b = new byte[chars.Length];
            //逐个字符变为16进制字节数据
            for (int i = 0; i < chars.Length; i++) {
                b[i] = Convert.ToByte(chars[i], 16);
            }
            //按照指定编码将字节数组变为字符串
            return encode.GetString(b);
        }

        /// <summary>
        /// 字符串转16进制字节数组
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        private static byte[] StrToToHexByte(string hexString) {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }


        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string ByteToHexStr(byte[] bytes) {
            string returnStr = "";
            if (bytes != null) {
                for (int i = 0; i < bytes.Length; i++) {
                    returnStr += bytes[i].ToString("X2");
                }
            }
            return returnStr;
        }



    }
}
